home *** CD-ROM | disk | FTP | other *** search
- /* AmiTrackShared.c -- Shared functions between client and server */
-
- #define __DICE_C
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
-
- #include <exec/types.h>
- #include <exec/io.h>
- #include <exec/lists.h>
- #include <exec/memory.h>
-
- #include <clib/exec_protos.h>
- #include <clib/alib_protos.h>
- #include <clib/dos_protos.h>
- #include <clib/intuition_protos.h>
-
- #include <errno.h>
- #include <inetd.h>
- #include <sys/types.h>
-
- #include <proto/socket.h>
- #include <proto/exec.h>
- #include <sys/errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/ioctl.h>
- #include <sys/syslog.h>
- #include <netdb.h>
-
- #include <intuition/intuition.h>
-
- #include <pragmas/socket_pragmas.h>
- #include <devices/timer.h>
-
-
- #include "AmiTrackShared.h"
-
- struct Library * TimerBase = NULL;
-
- void TrackExit(char * szMessage, int nCode)
- {
- if (nCode > 0) printf("Exiting, code %i: [%s]\n",nCode, szMessage);
- exit(nCode);
- }
-
-
- /* Wait for incoming packets or other relevant events */
- /* Returns a chord of event codes. May exit if a CTRL-C is detected. */
- ULONG TrackWait(struct SocketStuff * sTCP, struct SocketStuff * sUDP, struct TimerStuff * Timer, struct WindowStuff * Window, struct MsgPort * msgport)
- {
- struct fd_set fsReadSet;
- int nMaxPort = -1;
- ULONG ulCode = 0, ulMask = (Window ? (1L<<Window->win->UserPort->mp_SigBit) : 0L) |
- (Timer ? (1L<<Timer->TimerMP->mp_SigBit) : 0L) |
- (msgport ? (1L<<msgport->mp_SigBit) : 0L) |
- SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D;
-
- FD_ZERO(&fsReadSet);
- if (sUDP) {FD_SET(sUDP->fd, &fsReadSet); nMaxPort = sUDP->fd;}
- if (sTCP) {FD_SET(sTCP->fd, &fsReadSet); nMaxPort = (sTCP->fd > nMaxPort) ? sTCP->fd : nMaxPort;}
-
- /* Wait for Data to come in */
- /* socket# read write oob timeout other */
- WaitSelect(nMaxPort+1, &fsReadSet, NULL, NULL, NULL, &ulMask);
-
- if (ulMask & SIGBREAKF_CTRL_C) return(0L);
- if ((sUDP)&&(FD_ISSET(sUDP->fd, &fsReadSet))) ulCode |= CODE_UDP_SOCKET;
- if ((sTCP)&&(FD_ISSET(sTCP->fd, &fsReadSet))) ulCode |= CODE_TCP_SOCKET;
- if ((Timer)&&(ulMask & (1L<<Timer->TimerMP->mp_SigBit))) ulCode |= CODE_TIMER_EXPIRED;
- if (ulMask & SIGBREAKF_CTRL_D) ulCode |= CODE_REFRESH;
- if ((Window)&&(ulMask & (1L<<Window->win->UserPort->mp_SigBit))) ulCode |= CODE_WINDOW_EVENT;
- if ((msgport)&&(ulMask & (1L<<msgport->mp_SigBit))) ulCode |= CODE_MSGPORT;
- return(ulCode);
- }
-
-
-
- /* If clientList is NULL, sets up and returns a ClientList.
- If clientList is non-NULL, frees the ClientList and returns NULL. */
- struct ClientList * SetupClientList(struct ClientList * ClientList)
- {
- if (ClientList)
- {
- struct Client * current;
- while(current = (struct Client *)RemHead(&ClientList->list)) FreeClient(current);
- FreeMem(ClientList, sizeof(struct ClientList));
- return(NULL);
- }
- else
- {
- UNLESS(ClientList = AllocMem(sizeof(struct ClientList),MEMF_CLEAR)) return(NULL);
- NewList(&ClientList->list);
- return(ClientList);
- }
- }
-
-
-
-
-
-
- /* if ts is NULL, allocates and returns all the TimerStuff you need (or NULL on failure) */
- /* If ts is non-NULL, frees everything in ts, and returns NULL. */
- struct TimerStuff * SetupTimer(struct TimerStuff * ts)
- {
- #ifdef __DICE_C
- /* DICE seems to have a bug in it that makes it require this...
- otherwise tv_secs and tv_micro aren't recognized! :( */
- struct timeval {
- ULONG tv_secs;
- ULONG tv_micro;
- };
- #endif
-
- if (ts)
- {
- /* Deallocate everything! */
- if (ts->TimerIO)
- {
- if (ts->BDevOpen)
- {
- if (!(CheckIO((struct IORequest *)ts->TimerIO)))
- {
- AbortIO((struct IORequest *)ts->TimerIO); /* Ask device to abort any pending requests */
- WaitIO((struct IORequest *)ts->TimerIO); /* proceed when ready */
- }
- CloseDevice((struct IORequest *) ts->TimerIO);
- }
- DeleteExtIO((struct IORequest *) ts->TimerIO);
- }
- if (ts->TimerMP) DeletePort(ts->TimerMP);
- FreeMem(ts, sizeof(struct TimerStuff));
- return(NULL);
- }
- else
- {
- /* Set up the timer.device */
- UNLESS(ts = AllocMem(sizeof(struct TimerStuff), MEMF_CLEAR)) return(NULL);
- UNLESS((ts->TimerMP = CreatePort(0,0))
- && (ts->TimerIO = (struct timerequest *) CreateExtIO(ts->TimerMP, (sizeof (struct timerequest))))
- && (ts->BDevOpen = (0 == OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)ts->TimerIO,0))))
- return(SetupTimer(ts));
-
- TimerBase = (struct Library *) ts->TimerIO->tr_node.io_Device;
- ts->TimerIO->tr_node.io_Message.mn_ReplyPort = ts->TimerMP;
- ts->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
- ts->TimerIO->tr_node.io_Flags = 0;
- ts->TimerIO->tr_node.io_Error = 0;
- ts->TimerIO->tr_time.tv_secs = 0;
- ts->TimerIO->tr_time.tv_micro = 0;
- return(ts);
- }
- }
-
-
-
- /* Removes the client entry with the hostname szHostName from the ClientList. */
- /* Returns TRUE if an item was removed, else FALSE. */
- BOOL RemoveClient(struct ClientList * ClientList, char * szHostName)
- {
- struct Client * client = (struct Client *) ClientList->list.lh_Head;
-
- while(client->node.ln_Succ)
- {
- UNLESS(strcmp(szHostName, client->hostname))
- {
- /* found our victim! */
- Remove((struct Node *)client); FreeClient(client); ClientList->nListLength--;
- return(TRUE);
- }
- client = client->node.ln_Succ;
- }
- return(FALSE);
- }
-
-
-
- /* Frees the given client structure. Safe to use even if
- not all fields were allocated */
- void FreeClient(struct Client * client)
- {
- UNLESS(client) return;
- if (client->hostname) FreeMem(client->hostname, strlen(client->hostname)+1);
- if (client->comment) FreeMem(client->comment, strlen(client->comment)+1);
- FreeMem(client, sizeof(struct Client));
- }
-
-
-
-
-
- /* Set/Reset timer.device to signal us in nSecs seconds + nMicros microseconds */
- void SetTimer(struct TimerStuff * ts, int nSecs, int nMicros)
- {
- /* First make sure there is no previous timer pending */
- if (!(CheckIO((struct IORequest *) ts->TimerIO)))
- {
- AbortIO((struct IORequest *) ts->TimerIO);
- WaitIO((struct IORequest *) ts->TimerIO);
- }
-
- ts->TimerIO->tr_time.tv_secs = nSecs;
- ts->TimerIO->tr_time.tv_micro = nMicros;
-
- /* Start ze timer */
- SendIO((struct IORequest *)ts->TimerIO);
- }
-
-
-
- /* Find the client structure with the given hostname in the client list.
- Failing that, create one and insert it into the list. Failing
- that, return NULL. If szOptComment is non-NULL, it will be created/
- replaced in the returned Client. */
- struct Client * GetClient(struct ClientList * ClientList, ULONG ulIPAddress, char * szHostName, char * szOptComment)
- {
- struct Client * client = (struct Client *) ClientList->list.lh_Head;
- struct Client * prevClient = NULL;
- int nCompare;
-
- UNLESS(ulIPAddress) return(NULL);
-
- while (client->node.ln_Succ)
- {
- nCompare = strcmp(szHostName, client->hostname);
- if ((nCompare == 0)&&(ulIPAddress == client->ulIPAddress))
- {
- if (szOptComment) ReplaceAllocedString(&client->comment, szOptComment);
- return(client);
- }
- if (nCompare < 0) break; /* Not in the list--insert it here */
- prevClient = client;
- client = (struct Client *)client->node.ln_Succ;
- }
-
- /* If we got here, we need to add the client to the list */
- UNLESS(client = NewClient(ulIPAddress, szHostName, szOptComment)) return(NULL);
- Insert((struct List *)ClientList, (struct Node *)client, (struct Node *)prevClient); ClientList->nListLength++;
- return(client);
- }
-
-
-
- /* Allocate a new Client structure and initialize its fields correctly,
- or return NULL on failure. */
- struct Client * NewClient(ULONG ulIPAddress, char * szHostName, char * szOptComment)
- {
- struct Client * client = NULL;
-
- UNLESS(szOptComment) szOptComment = "";
- UNLESS((client = AllocMem(sizeof(struct Client), MEMF_CLEAR))
- && (client->hostname = AllocMem(strlen(szHostName)+1, MEMF_ANY))
- && (strcpy(client->hostname, szHostName))
- && (client->comment = AllocMem(strlen(szOptComment)+1, MEMF_ANY))
- && (strcpy(client->comment, szOptComment)))
- {
- FreeClient(client); /* cleanup any partial allocations */
- return(NULL);
- }
- client->ulIPAddress = ulIPAddress;
- client->tDateStamp = time(NULL);
- return(client);
- }
-
-
-
-
-
- /* Deallocate the old string, allocate the new string! */
- /* Give it a pointer to the pointer to the old string, and a pointer to the new string */
- /* Can also server to just deallocate the old, if the new string is NULL */
- void ReplaceAllocedString(char ** szOldString, char * szNewString)
- {
- char * pcTemp = NULL;
-
- UNLESS(szOldString) return;
- if (szNewString)
- {
- UNLESS(pcTemp = AllocMem(strlen(szNewString)+1, MEMF_ANY)) return;
- strcpy(pcTemp, szNewString);
- }
- if (*szOldString) FreeMem(*szOldString, strlen(*szOldString)+1);
- *szOldString = pcTemp;
- return;
- }
-
-
-
- /* If ss is NULL, allocates and returns a new SocketStuff structure.
- If ss is non-NULL, deallocates it and returns NULL. */
- struct SocketStuff * SetupSocket(struct SocketStuff * ss, int nPort, LONG lSocketType)
- {
- BOOL BBind = TRUE;
-
- /* If nPort is negative, use its absolute value and don't try to bind() it */
- if (nPort < 0)
- {
- nPort = -nPort;
- BBind = FALSE;
- }
-
- if (ss)
- {
- if (ss->fd >= 0) CloseSocket(ss->fd);
- FreeMem(ss, sizeof(struct SocketStuff));
- return(NULL);
- }
- else
- {
- UNLESS(ss = AllocMem(sizeof(struct SocketStuff), MEMF_CLEAR)) return(NULL);
- ss->lSocketType = lSocketType;
-
- if ((ss->fd = socket(AF_INET, ss->lSocketType, 0)) < 0) return(SetupSocket(ss,0,0));
-
- bzero(&ss->saAddr, sizeof(struct sockaddr_in));
- ss->saAddr.sin_family = AF_INET;
- ss->saAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- ss->saAddr.sin_port = htons(nPort);
- if ((BBind)&&(bind(ss->fd, (struct sockaddr *) &ss->saAddr, sizeof(struct sockaddr_in)))) return(SetupSocket(ss,0,0));
- return(ss);
- }
- }
-
-
-
-
- /* Downloads, allocates, and returns a ClientList if possible.
- Returns NULL on failure. */
- struct ClientList * GetTrackList(char * szHostName, int nPortNum)
- {
- struct ClientList * ClientList = NULL;
- struct SocketStuff * sSocket = NULL;
- struct hostent * hp;
- char * pcName, * pcComment;
- ULONG ulIPAddress;
-
- UNLESS(sSocket = SetupSocket(NULL, -nPortNum, SOCK_STREAM)) return(NULL);
- UNLESS(ClientList = SetupClientList(NULL))
- {
- SetupSocket(sSocket,0,0);
- return(NULL);
- }
- UNLESS(hp = gethostbyname(szHostName))
- {
- SetupSocket(sSocket,0,0);
- return(NULL);
- }
- bzero(&sSocket->saAddr, sizeof(struct sockaddr_in));
- bcopy(hp->h_addr, (char *)&sSocket->saAddr.sin_addr.s_addr, hp->h_length);
- sSocket->saAddr.sin_family = hp->h_addrtype;
- sSocket->saAddr.sin_port = htons(nPortNum);
-
- if (connect(sSocket->fd, (struct sockaddr *) &sSocket->saAddr, sizeof(struct sockaddr_in)) < 0)
- {
- SetupSocket(sSocket,0,0);
- SetupClientList(ClientList);
- return(NULL);
- }
-
- /* Now just read & record! */
- while(FillInfos(sSocket, &pcName, &ulIPAddress, &pcComment)) GetClient(ClientList, ulIPAddress, pcName, pcComment);
-
- SetupSocket(sSocket, 0, 0);
- return(ClientList);
- }
-
-
- /* Returns TRUE if *pSetName and *pSetComment are valid, else FALSE on error. */
- BOOL FillInfos(struct SocketStuff * sSocket, char **pSetName, ULONG * ulIPAddress, char **pSetComment)
- {
- static char szBuf[1000];
- ULONG nIndex = 0L;
- int nReadULONG = 0;
- char * pcIPBinary = (char *) ulIPAddress;
-
- *pSetName = szBuf;
- *pSetComment = NULL;
- *ulIPAddress = 0L;
-
- while(1)
- {
- if (recv(sSocket->fd, &szBuf[nIndex], 1, 0L) <= 0) return(FALSE);
- if (nReadULONG) /* we read the IP address as 4 binary bytes */
- {
- *pcIPBinary = szBuf[nIndex]; pcIPBinary++;
- UNLESS(--nReadULONG) return(TRUE);
- }
- else if (szBuf[nIndex] == '\0')
- {
- if (*pSetComment) nReadULONG = sizeof(ULONG);
- else *pSetComment = &szBuf[nIndex+1];
- }
-
- if ((++nIndex) >= sizeof(szBuf)) return(FALSE);
- }
- }
-
-
- void ClearTrackScreen(void)
- {
- printf("%c",12);
- }
-
- /* Server's output to stdout for the local user to see. */
- void PrintClientList(struct ClientList * ClientList)
- {
- struct Client * client = (struct Client *) ClientList->list.lh_Head;
- int nTemp = 0;
- time_t tTime = time(NULL);
-
- printf(" Num | Age | Hostname | Comment\n");
- printf("-----+-----+---------------------------+----------------------\n");
- while (client->node.ln_Succ)
- {
- printf("#%03i | %03lu | %-25s | %s\n",
- nTemp,tTime - client->tDateStamp,
- client->hostname,client->comment);
- client = client->node.ln_Succ;
- nTemp++;
- }
- putchar('\n');
- }
-
-
- int MakeReq(char *sTitle, char *sText, char *sGadgets)
- {
- struct EasyStruct myreq;
- int nResult;
-
- UNLESS(sTitle) sTitle = "AmiTrack Message";
- UNLESS(sText) sText = "Check this out!";
- UNLESS(sGadgets) sGadgets = "OK";
-
- myreq.es_TextFormat = sText;
- myreq.es_Title = sTitle;
- myreq.es_GadgetFormat = sGadgets;
-
- nResult = EasyRequest(NULL, &myreq, NULL, NULL, NULL);
-
- return(nResult);
- }
-
-
- /* Returns a pointer to the first non-space character in the string */
- char * PastSpaces(char * pcString)
- {
- while(1)
- {
- if (*pcString == ' ') pcString++;
- else return(pcString);
- }
- }
-
-
- /* Chops off any trailing blanks and returns the string */
- char * RemoveTrailingSpaces(char * pcString)
- {
- char * pcTemp = strchr(pcString,'\0');
-
- pcTemp--;
- while((pcTemp > pcString)&&(*pcTemp == ' ')) pcTemp--;
- pcTemp++;
-
- *pcTemp = '\0';
-
- return(pcTemp);
- }
-
-
- /* Replaces all unprintable characters in pcString with ' ' */
- /* Hopefully this will stop people from sending e.g. "talkbombs" */
- /* Returns pcString. */
- char * RemoveUnprintableChars(char * pcString)
- {
- char * pcTemp = pcString;
-
- while(*pcTemp)
- {
- if (*pcTemp < ' ') *pcTemp = ' ';
- pcTemp++;
- }
- return(pcString);
- }
-
-
- /* Makes pcString lower case */
- char * ToLower(char * pcString)
- {
- char * pcTemp = pcString;
-
- while(*pcTemp)
- {
- if ((*pcTemp >= 'A')&&(*pcTemp <= 'Z'))
- *pcTemp += 'a'-'A';
- pcTemp++;
- }
- return(pcString);
- }